#ifndef _WTK_BROADCAST_MSG_QUEUE_H_
#define _WTK_BROADCAST_MSG_QUEUE_H_

#include <pthread.h>
#include <semaphore.h>
#include "wtk/core/wtk_queue.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef void (*wtk_broadcast_msg_queue_gabbage_collector)(void* data, wtk_queue_node_t * qn);

typedef struct wtk_broadcast_msg_queue wtk_broadcast_msg_queue_t;

typedef struct{
    sem_t sem;
	wtk_queue_node_t * p_cur_node;
    int not_first:1;
}wtk_broadcast_msg_queue_reader_info_t;

static inline void wtk_broadcast_msg_queue_reader_info_init(wtk_broadcast_msg_queue_reader_info_t * info)
{
    sem_init(&(info->sem), 0, 0);
    info->not_first = 0;
	info->p_cur_node = NULL;
}

static inline void wtk_broadcast_msg_queue_reader_info_clear(wtk_broadcast_msg_queue_reader_info_t * info)
{
    sem_destroy(&(info->sem));
}

struct wtk_broadcast_msg_queue{
	wtk_queue_t q_msg;
	pthread_mutex_t msg_mutex;
	pthread_mutex_t process_mutex;
	pthread_cond_t cond;
	void * collector_data;
	wtk_broadcast_msg_queue_gabbage_collector collector;

	int receiver_num;
	
	wtk_broadcast_msg_queue_reader_info_t * info;
};

int wtk_broadcast_msg_queue_init(wtk_broadcast_msg_queue_t *q, int num, wtk_broadcast_msg_queue_gabbage_collector collector, void * data);

int wtk_broadcast_msg_queue_clear(wtk_broadcast_msg_queue_t *q);

int wtk_broadcast_msg_queue_broadcast(wtk_broadcast_msg_queue_t *q, wtk_queue_node_t *n);

wtk_queue_node_t* wtk_broadcast_msg_queue_get_msg(wtk_broadcast_msg_queue_t *q, int i);

int wtk_broadcast_msg_queue_return_msg(wtk_broadcast_msg_queue_t * q, int i);

/*!
*@brief fast sweep but in many cases the function left one item in the queue    
* wtk_broadcast_msg_queue_reset and wtk_broadcast_msg_queue_clear clean all the items
* but they are not thread safe
*/
int wtk_broadcast_msg_queue_sweep_gabbage(wtk_broadcast_msg_queue_t * q);

int wtk_broadcast_msg_queue_reset(wtk_broadcast_msg_queue_t * q);

#ifdef __cplusplus
}
#endif

#endif
